#include "ColorLegend.h"
#include <GL/glut.h>
#include <string>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include "Utilities.h"

using namespace std;

ColorLegend::ColorLegend()
:
    d_width(8.0),
    d_height(1.0),
    d_xpos(0.0),
    d_ypos(0.0),
    d_numColors(0),
    d_banded(false)
{}

ColorLegend::ColorLegend(double width, double height, double x, double y,
        ColorMap *map, std::string const &name)
:
    d_width(width),
    d_height(height),
    d_xpos(x),
    d_ypos(y),
    d_numColors(0),
    d_banded(false),
    d_map(map),
    d_min(0.0),
    d_max(1.0),
    d_dx(1.0),
    d_dy(1.0),
    d_name(name)
{}

void ColorLegend::draw()
{    
    glTranslatef(0.0, 0.0, -0.5);
    drawBackground();    
    glTranslatef(0.0, 0.0, 0.5);
    drawBitmapText(d_name, (0.2 * d_width + d_xpos) * d_dx,
        (0.9 * d_height + d_ypos) * d_dy, 12);
    drawColorsDisc();        
    drawNumbers();
    drawBorders();
}

void ColorLegend::draw(double x, double y, float winW, float winH, int dim)
{
    d_xpos = x;
    d_ypos = y;
    
    d_dx = double(winW) / (dim + 1);   // Grid cell width
    d_dy = double(winH) / (dim + 1);  // Grid cell heigh
    draw();
}

void ColorLegend::drawBackground()
{
    glColor3f(1.0f, 1.0f, 1.0f);
    glBegin(GL_QUADS);
        glVertex2f(d_xpos * d_dx, (d_ypos + d_height) * d_dy);              // Top Left
        glVertex2f(d_xpos * d_dx, d_ypos * d_dy);              // Bottom Left        
        glVertex2f((d_xpos + d_width) * d_dx, d_ypos * d_dy);              // Bottom Right
        glVertex2f((d_xpos + d_width) * d_dx, (d_ypos + d_height) * d_dy);              // Top Right
    glEnd();        

}
    
void ColorLegend::drawColorsCont()        
{
    
    fftw_real xpos = d_xpos + 0.1 * d_width;
    fftw_real ypos = d_ypos + 0.1 * d_height;
    fftw_real height = d_height * 0.7;
    fftw_real width = d_width * 0.3;    
    
    d_map->set(0.0, 1.0);
    glBegin(GL_QUADS);                      // Draw A Quad
    glVertex2f(xpos * d_dx, ypos * d_dy);              // Bottom Left       
    glVertex2f((xpos + width) * d_dx, ypos * d_dy);              // Bottom Right
    d_map->set(0.5, 1.0);
    for (int i = 0; i != 2; ++i)
    {
        glVertex2f((xpos + width) * d_dx, (ypos + height / 2) * d_dy);              // Top Right
        glVertex2f(xpos * d_dx, (ypos + height / 2) * d_dy);              // Top Left
    }
    d_map->set(1.0, 1.0);    
    glVertex2f(xpos * d_dx, (ypos + height) * d_dy);              // Top Left
    glVertex2f((xpos + width) * d_dx, (ypos + height) * d_dy);              // Top Right    
    
    glEnd();                            // Done Drawing The Quad        
    

    
}

void ColorLegend::setUnits(double x, double y)
{
    d_dx = x;
    d_dy = y;
}

void ColorLegend::drawColorsDisc()
{
    fftw_real xpos = d_xpos + 0.1 * d_width;
    fftw_real ypos = d_ypos + 0.1 * d_height;
    fftw_real height = d_height * 0.7;
    fftw_real width = d_width * 0.3;
    
    int numColors = d_map->levels();    
    fftw_real dH = height / numColors;
    
    d_map->set(0, 1.0);
    glBegin(GL_QUADS);
    
    glVertex2f(xpos * d_dx, ypos * d_dy); // bottom left
    glVertex2f((xpos + width) * d_dx,  ypos * d_dy); // bottom right
    
    for (int block = 1; block != numColors; ++block)
    {
        glVertex2f((xpos + width) * d_dx,  (ypos + block * dH) * d_dy); //top right
        glVertex2f(xpos * d_dx,  (ypos + block * dH) * d_dy); //top left    
        d_map->set(block, 1.0);
        glVertex2f( xpos * d_dx,  (ypos + block * dH) * d_dy); //bottom left
        glVertex2f( (xpos + width) * d_dx,  (ypos + block * dH) * d_dy); //bottom right        
    }             
    
    glVertex2f( (xpos + width) * d_dx,  (ypos + height) * d_dy);    // Top Right
    glVertex2f( xpos * d_dx,  (ypos + height) * d_dy);              // Top Left
    
    glEnd();   
    
}


void ColorLegend::drawBorders()
{
    fftw_real xpos = d_xpos + 0.1 * d_width;
    fftw_real ypos = d_ypos + 0.1 * d_height;
    fftw_real height = d_height * 0.7;
    fftw_real width = d_width * 0.3;
    
    glColor3f(0.0f, 0.0f, 0.0f);
    glBegin(GL_LINES);
        glVertex2f( xpos * d_dx,  (ypos + height) * d_dy);              // Top Left
        glVertex2f( xpos * d_dx,  (ypos) * d_dy);              // Bottom Left            
        glVertex2f( xpos * d_dx,  (ypos) * d_dy);              // Bottom Left            
        glVertex2f( (xpos + width) * d_dx,  (ypos) * d_dy);              // Bottom Right
        glVertex2f( (xpos + width) * d_dx,  (ypos) * d_dy);              // Bottom Right
        glVertex2f( (xpos + width) * d_dx,  (ypos + height) * d_dy);              // Top Right
        glVertex2f( (xpos + width) * d_dx,  (ypos + height) * d_dy);              // Top Right
        glVertex2f( xpos * d_dx,  (ypos + height) * d_dy);              // Top Left
    glEnd();
    
    int numbers = std::min(5, d_map->levels() + 1);
    double dH = height / (numbers - 1);
    double lineWidth = 0.15;
    
    glBegin(GL_LINES);
    
    for (int line = 0; line != numbers; ++line)
    {
        glVertex2f( (xpos + width) * d_dx,
                 (ypos + line * dH) * d_dy);
        glVertex2f( (xpos + width + lineWidth) * d_dx,
                 (ypos + line * dH) * d_dy);
    }
    
    glEnd();
}

void ColorLegend::drawNumbers()
{
    fftw_real xpos = d_xpos + 0.5 * d_width;
    fftw_real ypos = d_ypos + 0.1 * d_height - 0.15;
    fftw_real height = d_height * 0.7;    
    
    fftw_real max = d_map->usedMax();
    fftw_real min = d_map->usedMin();
    
    
    int numbers = std::min(5, d_map->levels() + 1);
    double dVal = (max - min) / (numbers - 1);
    double dH = height / (numbers - 1);
    
    for (int i = 0; i != numbers; ++i)
    {
        double val = min + i * dVal;
        ostringstream sstr;
        sstr << fixed << setprecision(2) << val;
        string drawString = sstr.str();        
        double drawY = ypos + i * dH;
        drawBitmapText(drawString,  xpos * d_dx,  drawY * d_dy, 10);        
    }
}
